﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="SafEnvironment.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights Reserved.
// </copyright>
// <summary>
//   Defines the SafEnvironment type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Collaboris.Saf.Utilities
{
    using System;
    using System.IO;

    using Microsoft.SharePoint.Administration;
    using Microsoft.Win32; 

    /// <summary>
    /// This class provides access to Environmental Information
    /// about SharePoint and Saf.
    /// </summary>
    /// <remarks>
    /// The class is a singleton/cached class and most properties are Lazy loaded on 
    /// first access. 
    /// </remarks>
    public sealed class SafEnvironment
    {
        #region private methods 

        private string internalTwelveFolder;
        private string internalImagesFolder;

        private string internalTemplatesFolder;

        private string internalFeaturesFolder;

        private string internalLayoutsFolder;

        private Version internalSharePointVersion;

        private Version internalSafVersion;

        private string internalSafConfigFolder;

        private SafEnvironment()
        {}

        private string GetSharePointDirectory()
        {
            string key = @"SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\12.0";
            string name = "Location";

            string path = String.Empty;
            try
            {
                RegistryKey regKey = Registry.LocalMachine.OpenSubKey(key);
                if (regKey != null)
                {
                    path = regKey.GetValue(name) as string;
                    regKey.Close();
                }
            }
            catch (Exception)
            {
                path = String.Empty;
            }

            return path;
        }
        
        private string InternalTwelveFolder
        {
            get
            {
                if (string.IsNullOrEmpty(this.internalTwelveFolder))
                    this.internalTwelveFolder = this.GetSharePointDirectory();

                if (string.IsNullOrEmpty(this.internalTwelveFolder))
                {
                    string programFilesPath = Environment.GetEnvironmentVariable("ProgramFiles");
                    string twelveHivePath = string.Concat(programFilesPath,
                                                @"\Common Files\Microsoft Shared\web server extensions\12\");
                    if (!Directory.Exists(twelveHivePath))
                    {
                        this.internalTwelveFolder = twelveHivePath.Replace("(x86)", string.Empty);
                    }
                    else
                    {
                        this.internalTwelveFolder = twelveHivePath;
                    }
                }
                
                return this.internalTwelveFolder;
            }
        }

        /// <summary>
        /// Gets the path to the Templates Folder.
        /// </summary>
        /// <value>The templates FLDR.</value>
        private string InternalTemplatesFolder
        {
            get
            {
                if (string.IsNullOrEmpty(this.internalTemplatesFolder))
                {
                    this.internalTemplatesFolder = Path.Combine(this.InternalTwelveFolder, @"TEMPLATE\");
                }

                return this.internalTemplatesFolder;
            }
        }

        private string InternalLayoutsFolder
        {
            get
            {
                if (string.IsNullOrEmpty(this.internalLayoutsFolder))
                {
                    this.internalLayoutsFolder = Path.Combine(this.InternalTwelveFolder, @"TEMPLATE\LAYOUTS\");
                }
                return this.internalLayoutsFolder;
            }
        }

        private string InternalImagesFolder
        {
            get
            {
                if (string.IsNullOrEmpty(this.internalImagesFolder))
                {
                    this.internalImagesFolder = Path.Combine(this.InternalTwelveFolder, @"TEMPLATE\IMAGES\");
                }

                return this.internalImagesFolder;
            }
        }

        private string InternalFeaturesFolder
        {
            get
            {
                if (string.IsNullOrEmpty(this.internalFeaturesFolder))
                {
                    this.internalFeaturesFolder = Path.Combine(this.InternalTwelveFolder, @"TEMPLATE\FEATURES\");
                }

                return this.internalFeaturesFolder;
            }
        }

        private Version InternalSharePointVersion
        {
            get
            {
                if (this.internalSharePointVersion == null)
                    this.internalSharePointVersion = SPFarm.Local.BuildVersion;

                return this.internalSharePointVersion;
            }
        }

        private Version InternalSafVersion
        {
            get
            {
                if (this.internalSafVersion == null)
                    this.internalSafVersion = this.GetType().Assembly.GetName().Version;

                return this.internalSafVersion;
            }
        }

        private string InternalSafConfigFolder
        {
            get
            {
                if (this.internalSafConfigFolder == null)
                {
                    // sets to something like this ...
                    //   C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\CONFIG\Collaboris\v1.3
                    this.internalSafConfigFolder = Path.Combine(
                        this.InternalTwelveFolder,
                        @"CONFIG\Collaboris\v" + this.InternalSafVersion.Major + "." + this.InternalSafVersion.Minor);

                    if (!Directory.Exists(this.internalSafConfigFolder))
                    {
                        // TODO: Refactor into a single method.

                        // For whatever reason the collaboris config doesn't exist.                         
                        // Get it again from the environment variable.
                        string programFilesPath = Environment.GetEnvironmentVariable("ProgramFiles");
                        string twelveHivePath = string.Concat(programFilesPath,
                                                    @"\Common Files\Microsoft Shared\web server extensions\12\");

                        if (!Directory.Exists(twelveHivePath))
                        {
                            this.internalTwelveFolder = twelveHivePath.Replace("(x86)", string.Empty);
                        }
                        else
                        {
                            this.internalTwelveFolder = twelveHivePath;
                        }

                        // get the collaboris config path...
                        this.internalSafConfigFolder = Path.Combine(this.InternalTwelveFolder,
                            @"CONFIG\Collaboris\v" + this.InternalSafVersion.Major + "." + this.InternalSafVersion.Minor);
                    }
                    else
                    {
                        // Note: This is used only for testing. When we get any error on the path because of 32/64 bit problem.
                        string collaborisEnvironmentConfigPath = Environment.GetEnvironmentVariable("CollaborisConfigPath");
                        // Overwrite the config path using the Environment config path.
                        // if NOT null/empty carry on...
                        if (!string.IsNullOrEmpty(collaborisEnvironmentConfigPath))
                        {
                            this.internalSafConfigFolder = Environment.GetEnvironmentVariable("CollaborisConfigPath");
                        }
                    }
                }

                return this.internalSafConfigFolder;
            }
        }

        #endregion

        #region static methods

        /// <summary>
        /// Gets the saf aliases file path.
        /// </summary>
        /// <value>The saf aliases file path.</value>
        public static string SafAliasesFilePath
        {
            get
            {
                return Path.Combine(Instance.InternalSafConfigFolder, "SafAliases.xml");
            }
        }

        /// <summary>
        /// Gets the saf manifest file path.
        /// </summary>
        /// <value>The saf manifest file path.</value>
        public static string SafManifestFilePath
        {
            get
            {
                return Path.Combine(Instance.InternalSafConfigFolder, "SafManifest.xml");
            }
        }

        /// <summary>
        /// Gets the path to the current Folder 
        /// </summary>
        /// <value>The saf version.</value>
        public static string SafConfigFolder
        {
            get
            {
                return Instance.InternalSafConfigFolder;
            }
        }

        /// <summary>
        /// Gets the saf version.
        /// </summary>
        /// <value>The saf version.</value>
        public static Version SafVersion
        {
            get
            {
                return Instance.InternalSafVersion;
            }
        }

        /// <summary>
        /// Gets the sharepoint version.
        /// </summary>
        /// <value>The share point version.</value>
        public static Version SharePointVersion
        {
            get
            {
                return Instance.InternalSharePointVersion;
            }
        }

        /// <summary>
        /// Gets the path to the Features folder.
        /// </summary>
        /// <value>The features folder.</value>
        public static string FeaturesFolder
        {
            get
            {
                return Instance.InternalFeaturesFolder;
            }
        }

        /// <summary>
        /// Gets the path to the Templates folder.
        /// </summary>
        /// <value>The templates folder.</value>
        public static string TemplatesFolder
        {
            get
            {
                return Instance.InternalTemplatesFolder;
            }
        }

        /// <summary>
        /// Gets the path to the images folder.
        /// </summary>
        /// <value>The images folder.</value>
        public static string ImagesFolder
        {
            get
            {
                return Instance.InternalImagesFolder;
            }
        }

        /// <summary>
        /// Gets the Path to the layouts folder.
        /// </summary>
        /// <value>The layouts folder.</value>
        public static string LayoutsFolder
        {
            get
            {
                return Instance.InternalLayoutsFolder;
            }
        }

        /// <summary>
        /// Gets the Path to the 12 hive folder.
        /// </summary>
        /// <value>The layouts folder.</value>
        public static string TwelveFolder
        {
            get
            {
                return Instance.InternalTwelveFolder;
            }
        }

        /// <summary>
        /// Gets the a singleton.
        /// </summary>
        /// <value>The instance.</value>
        public static SafEnvironment Instance
        {
            get
            {
                return Singleton.instance;
            }
        }

        #endregion

        class Singleton
        {
            static Singleton()
            {
            }

            internal static readonly SafEnvironment instance = new SafEnvironment();
        }
    }
}